package com.app.brilliant.sms;

import com.app.brilliant.common.exception.BusinessException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 短信验证码缓存服务
 */
@Service
public class SmsVerificationCacheService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private static final String SMS_CODE_PREFIX = "sms:code:";
    private static final String SMS_SEND_COUNT_PREFIX = "sms:count:";
    private static final String SMS_IP_LIMIT_PREFIX = "sms:ip:";

    /**
     * 保存验证码
     * @param phone 手机号
     * @param code 验证码
     * @param bizType 业务类型
     * @param expireMinutes 过期时间（分钟）
     */
    public void saveCode(String phone, String code, String bizType, int expireMinutes) {
        String key = SMS_CODE_PREFIX + bizType + ":" + phone;
        redisTemplate.opsForValue().set(key, code, expireMinutes, TimeUnit.MINUTES);
    }

    /**
     * 验证验证码
     * @param phone 手机号
     * @param code 验证码
     * @param bizType 业务类型
     * @return 是否验证通过
     */
    public boolean verifyCode(String phone, String code, String bizType) {
        String key = SMS_CODE_PREFIX + bizType + ":" + phone;
        String storedCode = redisTemplate.opsForValue().get(key);
        if (storedCode == null || !storedCode.equals(code)) {
            return false;
        }
        // 验证成功后删除验证码
        redisTemplate.delete(key);
        return true;
    }

    /**
     * 检查发送频率限制
     * @param phone 手机号
     * @param bizType 业务类型
     * @param intervalSeconds 间隔时间（秒）
     * @return 是否允许发送
     */
    public boolean checkSendFrequency(String phone, String bizType, int intervalSeconds) {
        String key = SMS_SEND_COUNT_PREFIX + bizType + ":" + phone;
        Long lastSendTime = redisTemplate.opsForValue().getOperations().getExpire(key);
        if (lastSendTime != null && lastSendTime > 0) {
            throw new BusinessException("操作过于频繁，请稍后再试");
        }
        redisTemplate.opsForValue().set(key, "1", intervalSeconds, TimeUnit.SECONDS);
        return true;
    }

    /**
     * 检查每日发送上限
     * @param phone 手机号
     * @param bizType 业务类型
     * @param maxCount 最大发送次数
     * @return 是否允许发送
     */
    public boolean checkDailyLimit(String phone, String bizType, int maxCount) {
        String key = SMS_SEND_COUNT_PREFIX + bizType + ":daily:" + phone;
        Long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == null) {
            return true;
        }
        if (count == 1) {
            redisTemplate.expire(key, 24, TimeUnit.HOURS);
        }
        if (count > maxCount) {
            throw new BusinessException("今日发送次数已达上限");
        }
        return true;
    }

    /**
     * 检查IP请求频率
     * @param ip IP地址
     * @param intervalSeconds 间隔时间（秒）
     * @return 是否允许发送
     */
    public boolean checkIpFrequency(String ip, int intervalSeconds) {
        String key = SMS_IP_LIMIT_PREFIX + ip;
        Long lastRequestTime = redisTemplate.opsForValue().getOperations().getExpire(key);
        if (lastRequestTime != null && lastRequestTime > 0) {
            throw new BusinessException("操作过于频繁，请稍后再试");
        }
        redisTemplate.opsForValue().set(key, "1", intervalSeconds, TimeUnit.SECONDS);
        return true;
    }
}